package blacklist

import (
	"dfx_cmdb/cmdb-agent/global"
	"dfx_cmdb/cmdb-agent/middleware"
	"dfx_cmdb/cmdb-agent/types"
	"fmt"
	"sync"

	"gitee.com/daofeixian/dfx_golang_toolset/common/res"
	"github.com/gin-gonic/gin"
	"github.com/zeromicro/go-zero/core/logc"
)

type AgentBlackListApi struct {
}
type AgentBlackListStatus types.BlackList

type AgentBlacklistCron struct {
	Crontab string `json:"crontab" binding:"required"`
}

func (a *AgentBlackListApi) SetBlacklistStatus(c *gin.Context) {
	ctx := c.Request.Context()
	cr := middleware.GetBind[AgentBlackListStatus](c)
	reqFunc := types.BlackList(cr)

	tempSt := sync.Map{}
	tempSt.Store(global.CMDB_BLACKLIST_HAPROXY_NAME, reqFunc.Haproxy)
	tempSt.Store(global.CMDB_BLACKLIST_EBPF_NAME, reqFunc.EBPF)
	tempSt.Store(global.CMDB_BLACKLIST_OPENRESTY_NAME, reqFunc.Openresty)
	hb, err := global.CheckConfigBlacklistStatus(ctx)
	if err != nil {
		logc.Errorf(ctx, "error: %v", err)
		return
	}
	for _, v := range global.BlacklistTypeModes {
		tv, _ := tempSt.Load(v)
		gv, _ := global.BlacklistCronStatusMap.Load(v)
		if tv.(bool) && gv.(bool) {
			res.FailWithMsg(fmt.Sprintf("黑名单：%v 类型已开启，无需再次开启", v), c)
			return
		}
		blackStatus, err := GetBlacklistHandler(v)
		if err != nil {
			logc.Errorf(ctx, "获取黑名单处理器失败，错误信息: %v", err)
			res.FailWithMsg(fmt.Sprintf("获取黑名单：%v 处理器失败", v), c)
			return
		}
		if global.Svc.CronJobId != 0 {
			global.Svc.Cron.Remove(global.Svc.CronJobId)
			global.Svc.CronJobId = 0
		}

		global.Svc.CronJobId, err = global.Svc.Cron.AddFunc(global.Svc.Config.Function.Crontab, func() {
			err = blackStatus.EnableBlacklist(ctx)
			if err != nil {
				logc.Errorf(ctx, "黑名单：%v 定时任务执行失败，错误信息: %v", v, err)
				return
			}
		})
		if tv.(bool) {
			global.AppStatus[global.AGENT_BLACKLIST] = tv.(bool)
		}

		if err != nil {
			logc.Errorf(ctx, "启动黑名单：%v 任务失败，错误信息: %v", v, err)
			res.FailWithMsg(fmt.Sprintf("启动黑名单：%v 任务失败", v), c)
			return
		}
	}

	if hb {
		global.BlacklistCronStatusMap = &tempSt
		hv, _ := global.BlacklistCronStatusMap.Load(global.CMDB_BLACKLIST_HAPROXY_NAME)
		ov, _ := global.BlacklistCronStatusMap.Load(global.CMDB_BLACKLIST_OPENRESTY_NAME)
		ev, _ := global.BlacklistCronStatusMap.Load(global.CMDB_BLACKLIST_EBPF_NAME)
		global.Svc.Config.Function.BlackList.Haproxy = hv.(bool)
		global.Svc.Config.Function.BlackList.Openresty = ov.(bool)
		global.Svc.Config.Function.BlackList.EBPF = ev.(bool)
	}
	respBlacklistStatus := &types.Function{
		BlackList: types.BlackList{
			Haproxy:   global.Svc.Config.Function.BlackList.Haproxy,
			EBPF:      global.Svc.Config.Function.BlackList.EBPF,
			Openresty: global.Svc.Config.Function.BlackList.Openresty,
		},
		Crontab: global.Svc.Config.Function.Crontab,
	}

	res.OK(respBlacklistStatus, "黑名单状态修改成功", c)
}

func (a *AgentBlackListApi) GetBlacklistStatus(c *gin.Context) {
	res.OK(global.Svc.Config.Function, "获取黑名单状态成功", c)
}

func (a *AgentBlackListApi) SetBlacklistCron(c *gin.Context) {
	ctx := c.Request.Context()
	cr := middleware.GetBind[AgentBlacklistCron](c)
	count := 0
	var key string
	for _, v := range global.BlacklistTypeModes {
		gv, _ := global.BlacklistCronStatusMap.Load(v)
		if gv.(bool) {
			key = v
			count++
		}
	}
	if count == 0 {
		res.FailWithMsg("请先开启黑名单模式", c)
		return
	}

	global.Svc.Config.Function.Crontab = cr.Crontab

	global.Svc.Cron.Remove(global.Svc.CronJobId)
	global.Svc.CronJobId = 0

	blackStatus, err := GetBlacklistHandler(key)
	if err != nil {
		logc.Errorf(ctx, "获取黑名单处理器失败，错误信息: %v", err)
		res.FailWithMsg(fmt.Sprintf("获取黑名单：%v 处理器失败", key), c)
		return
	}

	global.Svc.CronJobId, err = global.Svc.Cron.AddFunc(global.Svc.Config.Function.Crontab, func() {
		err = blackStatus.EnableBlacklist(ctx)
		if err != nil {
			logc.Errorf(ctx, "黑名单：%v 定时任务执行失败，错误信息: %v", key, err)
			return
		}
	})
	if err != nil {
		logc.Errorf(ctx, "启动黑名单：%v 任务失败，错误信息: %v", key, err)
		res.FailWithMsg(fmt.Sprintf("启动黑名单：%v 任务失败", key), c)
		return
	}

	respBlacklistStatus := &types.Function{
		BlackList: types.BlackList{
			Haproxy:   global.Svc.Config.Function.BlackList.Haproxy,
			EBPF:      global.Svc.Config.Function.BlackList.EBPF,
			Openresty: global.Svc.Config.Function.BlackList.Openresty,
		},
		Crontab: global.Svc.Config.Function.Crontab,
	}

	res.OK(respBlacklistStatus, "定时任务修改成功", c)
}
